package cn.wizzer.app.web.modules.controllers.platform.sys;

import cn.wizzer.app.sys.modules.models.Sys_user;
import cn.wizzer.app.sys.modules.services.SysLangLocalService;
import cn.wizzer.app.sys.modules.services.SysUserService;
import cn.wizzer.app.web.commons.utils.StringUtil;
import cn.wizzer.framework.base.Result;
import com.alibaba.dubbo.config.annotation.Reference;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@IocBean
@At("/api/{version}/platform/sys/user")
@Ok("json")
@ApiVersion("1.0.0")
public class SysUserController {
    private static final Log log = Logs.get();
    @Inject
    @Reference
    private SysUserService sysUserService;
    @Inject
    @Reference
    private SysLangLocalService sysLangLocalService;

    /**
     * @api {get} /api/1.0.0/platform/sys/user/logon_user_info 获取当前用户菜单及角色
     * @apiName logon_user_info
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     * @apiSuccess {Object} data  数据对象
     * @apiSuccess {Object} data.user  用户数据
     * @apiSuccess {Object} data.menus  用户菜单
     * @apiSuccess {Object} data.roles  用户角色
     */
    @At("/logon_user_info")
    @Ok("json:{locked:'password|salt',ignoreNull:false}")
    @GET
    @RequiresAuthentication
    public Object getLogonUserInfo(HttpSession session) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (subject != null) {
                Sys_user user = (Sys_user) subject.getPrincipal();
                if (user != null) {
                    return Result.success().addData(
                            NutMap.NEW()
                                    .addv("lang", sysLangLocalService.getLocal())
                                    .addv("user", user)
                                    .addv("token", session.getAttribute("userToken"))
                                    .addv("menus", sysUserService.getMenusAndButtons(user.getId()))
                                    .addv("roles", sysUserService.getRoles(user)));
                }
            }
            return Result.error(500211, "system.login.norole");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }

    /**
     * @api {post} /api/1.0.0/platform/sys/user/set_user_theme 设置用户布局及样式
     * @apiName set_user_theme
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     */
    @At("/set_user_theme")
    @Ok("json")
    @POST
    @RequiresAuthentication
    public Object setUserThemeConfig(@Param("themeConfig") String themeConfig) {
        try {
            sysUserService.update(Chain.make("themeConfig", themeConfig), Cnd.where("id", "=", StringUtil.getPlatformUid()));
            Subject subject = SecurityUtils.getSubject();
            Sys_user user = (Sys_user) subject.getPrincipal();
            if (user != null)//替换当前用户session里的值
                user.setThemeConfig(themeConfig);
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }

    /**
     * @api {post} /api/1.0.0/platform/sys/user/change_user_info 修改当前用户信息
     * @apiName change_user_info
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     */
    @At("/change_user_info")
    @Ok("json")
    @RequiresAuthentication
    public Object doChangeInfo(@Param("username") String username, @Param("email") String email, @Param("mobile") String mobile, @Param("avatar") String avatar, HttpServletRequest req) {
        try {
            Subject subject = SecurityUtils.getSubject();
            Sys_user user = (Sys_user) subject.getPrincipal();
            if (user != null) {
                if (Strings.isNotBlank(email)) {
                    if (sysUserService.count(Cnd.where("email", "=", email).and("id", "<>", user.getId())) > 0) {
                        return Result.error().addMsg("sys.user.error.emailExisted");
                    }
                }
                if (Strings.isNotBlank(mobile)) {
                    if (sysUserService.count(Cnd.where("mobile", "=", mobile).and("id", "<>", user.getId())) > 0) {
                        return Result.error().addMsg("sys.user.error.mobileExisted");
                    }
                }
                sysUserService.update(Chain.make("username", username)
                                .add("avatar", avatar)
                                .add("email", email)
                                .add("mobile", mobile)
                        , Cnd.where("id", "=", user.getId()));
                user.setUsername(username);
                user.setAvatar(avatar);
                user.setEmail(email);
                user.setMobile(mobile);
                sysUserService.deleteCache(user.getId());
            }
            return Result.success();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }

    /**
     * @api {post} /api/1.0.0/platform/sys/user/change_user_pwd 修改当前用户密码
     * @apiName change_user_pwd
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     */
    @At("/change_user_pwd")
    @Ok("json")
    @RequiresAuthentication
    public Object doChangePassword(@Param("oldPassword") String oldPassword, @Param("newPassword") String newPassword, HttpServletRequest req) {
        try {
            Subject subject = SecurityUtils.getSubject();
            Sys_user user = (Sys_user) subject.getPrincipal();
            String old = new Sha256Hash(oldPassword, user.getSalt(), 1024).toHex();
            if (old.equals(user.getPassword())) {
                String salt = R.UU32();
                String hashedPasswordBase64 = new Sha256Hash(newPassword, ByteSource.Util.bytes(salt), 1024).toHex();
                user.setSalt(salt);//替换当前用户session里的值
                user.setPassword(hashedPasswordBase64);//替换当前用户session里的值
                sysUserService.update(Chain.make("salt", salt)
                                .add("password", hashedPasswordBase64)
                        , Cnd.where("id", "=", user.getId()));
                sysUserService.deleteCache(user.getId());
                return Result.success();
            } else {
                return Result.error().addMsg("sys.user.change.pwd.oldPwdError");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }

    /**
     * @api {get} /api/1.0.0/platform/sys/user/info_by_id/:userId 查询用户信息
     * @apiName info_by_id
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiParam {String} userId   用户ID
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     * @apiSuccess {Object} data  用户数据
     */
    @At("/info_by_id/?")
    @Ok("json:{locked:'password|salt',ignoreNull:false}")
    @GET
    @RequiresAuthentication
    public Object getInfoByUserId(String userId) {
        try {
            Sys_user sysUser = sysUserService.fetch(userId);
            if (sysUser == null) {
                return Result.error().addMsg("sys.user.not.exist");
            }
            return Result.success().addData(sysUser);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }

    /**
     * @api {get} /api/1.0.0/platform/sys/user/info_by_loginname/:loginname 查询用户信息
     * @apiName info_by_loginname
     * @apiGroup SYS_USER
     * @apiPermission 登陆用户
     * @apiVersion 1.0.0
     * @apiParam {String} loginname 登陆账号
     * @apiSuccess {Number} code  0
     * @apiSuccess {String} msg   操作成功
     * @apiSuccess {Object} data  用户数据
     */
    @At("/info_by_loginname/?")
    @Ok("json:{locked:'password|salt',ignoreNull:false}")
    @GET
    @RequiresAuthentication
    public Object getInfoByLoginname(String loginname) {
        try {
            Sys_user sysUser = sysUserService.fetch(Cnd.where("loginname", "=", loginname));
            if (sysUser == null) {
                return Result.error().addMsg("sys.user.not.exist");
            }
            return Result.success().addData(sysUser);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return Result.error();
    }
}
